﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using OpenSees.XML;
using PGMHelper;
using System.Windows.Forms.DataVisualization.Charting;

namespace OS_XML_Form
{
    public partial class MainForm : Form
    {
        #region XML基本对象

        /// <summary>
        /// X轴分析结果
        /// </summary>
        private ElementXML XAxisXML { set; get; }

        /// <summary>
        /// Y轴分析结果
        /// </summary>
        private ElementXML YAxisXML { set; get; }

        /// <summary>
        /// 时程分析结果
        /// </summary>
        private BasicXML TimeHistXML { set; get; }

        /// <summary>
        /// 临时XML变量
        /// </summary>
        private BasicXML TemporaryXML { set; get; }

        /// <summary>
        /// 单元分析结果
        /// </summary>
        private ElementDataSet ElementDatas { set; get; }

        /// <summary>
        /// 基本宽度
        /// </summary>
        private int TabelBasicWidth { set; get; }

        /// <summary>
        /// 基本高度
        /// </summary>
        private int TabelHeight { set; get; }

        #endregion

        /// <summary>
        /// 构造函数
        /// </summary>
        public MainForm()
        {
            InitializeComponent();
            //基本变量
            this.TabelHeight = 30;
            this.TabelBasicWidth = 100;
            //TabControl外观
            this.HysteresisTabControl.SetApperance();
            //Chart外观
            this.HysteresisChart.SetApperance(StringAlignment.Center, false);
            //Chart标题
            this.HysteresisChart.AddTitles("Hysteresis Loops", string.Empty, string.Empty);
            this.HysteresisChart.Titles[2].TextOrientation = TextOrientation.Rotated270;
            //科学记数
            this.HysteresisChart.SetAxisFormat(ChartAxisType.AxisX, AxisFormat.Science, 1, 1);
            this.HysteresisChart.SetAxisFormat(ChartAxisType.AxisY, AxisFormat.Science, 1, 1);
            //GridView外观
            this.HysteresisDataGridView.SetApperance( DataGridViewSelectionMode.ColumnHeaderSelect);
            //控件禁用
            this.TagGroupbox.Enabled = false;
            this.TimeHistResponseGroupbox.Enabled = false;
            this.TimeHistPlotButton.Enabled = false;
            this.ElementTagGroupBox.Enabled = false;
            this.HysteresisResponseGroupbox.Enabled = false;
            this.HysteresisPlotButton.Enabled = false;
        }

        #region 选择XML文件

        /// <summary>
        /// 选择X轴分析结果
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void X_Axis_Select_Button_Click(object sender, EventArgs e)
        {
            //获得XML对象
            if (this.GetXMLObject(this.XAxisSelec_Button, "X Axis") && this.TemporaryXML is ElementXML)
            {
                this.XAxisXML = (ElementXML)this.TemporaryXML;
                this.RefreshElementTagCheckListbox();
            }
            else this.XAxisXML = null;
        }

        /// <summary>
        /// 选择Y轴分析结果
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Y_Axis_Select_Button_Click(object sender, EventArgs e)
        {
            //获得XML对象
            if (GetXMLObject(Y_Axis_Select_Button, "Y Axis") && this.TemporaryXML is ElementXML)
            {
                this.YAxisXML = (ElementXML)this.TemporaryXML;
                RefreshElementTagCheckListbox();
            }
            else this.YAxisXML = null;   
        }

        /// <summary>
        /// 选择XML文件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void XML_Select_Button_Click(object sender, EventArgs e)
        {
            //获得XML对象
            if (GetXMLObject(XML_Select_Button, "Select XML File"))
            {
                //获得XML对象
                this.TimeHistXML = this.TemporaryXML;
                //刷新控件
                RefreshTagCheckListbox();
            }
            else this.TimeHistXML = null;   
        }

        /// <summary>
        /// 获取XML对象
        /// </summary>
        /// <param name="xml"></param>
        /// <param name="button"></param>
        /// <param name="orginText"></param>
        private bool GetXMLObject(Button button, string orginText)
        {
            //修改文字
            button.Text = orginText;
            //文件路径
            string filePath = string.Empty;
            //选择文件
            if (!WilsonHelper.OpenFile("XML(*.xml)|*.xml|文本文件(*.txt)|*.txt|所有文件(*.*)|*.*", ref filePath))
                return false;
            //获得结果
            this.TemporaryXML = OpenSeesXML.GetXMLResponse(filePath);
            //是否成功
            if (!this.TemporaryXML.isSuccess) return MessageBoxExtern.Error("Something Wrong!");
            //判断是否为单元对象
            if(this.TemporaryXML is ElementXML && orginText.Contains("select"))
                return MessageBoxExtern.Error("Only Element Object Available!");
            //成功修改按钮文字
            button.Text = "OK";
            return true;
        }

        #endregion

        #region 刷新控件

        /// <summary>
        /// 刷新单元编号列表
        /// </summary>
        private bool RefreshElementTagCheckListbox()
        {
            //控件控制函数指针
            Func<bool, bool> setControlEnabeld = isEnable =>
            {
                this.ElementTagGroupBox.Enabled = isEnable;
                this.HysteresisResponseGroupbox.Enabled = isEnable;
                this.HysteresisPlotButton.Enabled = isEnable;
                return isEnable;
            };
            //控件禁用
            setControlEnabeld(false);
            //避免值为空
            if (this.XAxisXML == null || this.YAxisXML == null) return false;
            //获得单元组分析结果
            this.ElementDatas = new ElementDataSet(this.XAxisXML, this.YAxisXML);
            //数据绑定
            this.ElementTagCheckListbox.SetDataSource(this.ElementDatas.Datas, "ID", "ID");
            //若无单元符合返回
            if (this.ElementDatas.Count == 0) return MessageBoxExtern.Error("NO Same Element Tag.");
            //更新ConboBox
            this.RefreshComboBox(this.XAxisComboBox, this.XAxisXML.GetResponseTypeList(false));
            this.RefreshComboBox(this.YAxisComboBox, this.YAxisXML.GetResponseTypeList(false));
            //全选
            this.ElementTagCheckListbox.CheckedAll();
            //控件开启
            return setControlEnabeld(true);
        }

        /// <summary>
        /// 刷新编号列表
        /// </summary>
        private bool RefreshTagCheckListbox()
        {
            //控件控制函数指针
            Func<bool, bool> setControlEnabeld = isEnable =>
            {
                this.TagGroupbox.Enabled = isEnable;
                this.TimeHistResponseGroupbox.Enabled = isEnable;
                this.TimeHistPlotButton.Enabled = isEnable;
                return isEnable;
            };
            //控件禁用
            setControlEnabeld(false);
            //避免值为空
            if (this.TimeHistXML == null) return false;
            //刷新
            this.TagChecklistbox.SetDataSource(this.TimeHistXML.ResponseList, "ID", "ID");
            //更新ConboBox
            this.RefreshComboBox(this.ResponseComboBox, this.TimeHistXML.GetResponseTypeList(false));
            //全选
            this.TagChecklistbox.CheckedAll();
            //控件开启
            return setControlEnabeld(true);
        }

        /// <summary>
        /// 修改下拉菜单栏
        /// </summary>
        /// <param name="box"></param>
        /// <param name="Response_list"></param>
        private void RefreshComboBox(ComboBox box ,List<string> Response_list)
        {
            //初始化
            box.Text = string.Empty;
            box.Items.Clear();
            //响应为空
            if (Response_list.Count == 0) return;
            //遍历
            foreach (string response in Response_list)
                box.Items.Add(response);
            //问题替换
            box.Text = box.Items[0].ToString();
        }

        /// <summary>
        /// 改变坐标轴文字
        /// </summary>
        /// <param name="titleList"></param>
        private void SetChartTitleText(List<string> txtList)
        {
            //判断数目是否相符
            if (txtList.Count != 3) return;
            //设定坐标轴文字
            this.HysteresisChart.SetTitle(TiltleType.Header, txtList[0]);
            this.HysteresisChart.SetTitle(TiltleType.AxisX, txtList[1]);
            this.HysteresisChart.SetTitle(TiltleType.AxisY, txtList[2]);
        }

        #endregion

        /// <summary>
        /// 时间响应时程
        /// </summary>
        /// <param name="descp"></param>
        /// <returns></returns>
        public GridViewDatas TimeHistData(string descp)
        {
            //初始化
            var data = new GridViewDatas("Time History");
            //获得时间列表
            var timeList = this.TimeHistXML.TimeList;
            //加入第一列时间
            data.Add(new GridViewColumn(timeList, demical: 2, titleName: "时间"));
            //获得勾选的对象
            var responseList = this.TagChecklistbox.GetObjects().ConvertAll(r => (Response)r);
            //遍历响应添加值
            responseList.ForEach(response =>
            {
                //获得响应列表
                var valueList = response[descp];
                //判断值是否相同
                if (valueList.Count == timeList.Count)
                {
                    data.Add(new GridViewColumn(valueList, demical: 2, format: "E2", 
                        titleName: response.ID.ToString()));
                    //创建序列
                    this.HysteresisChart.AddSeries(response.ID.ToString(), SeriesChartType.Line, 2);
                    //添加绘图数据
                    this.HysteresisChart.Series[response.ID.ToString()].Points.DataBindXY(timeList, valueList);
                }
            });
            //返回结果
            return data;
        }

        /// <summary>
        /// 滞回曲线
        /// </summary>
        /// <param name="xDescp"></param>
        /// <param name="yDescp"></param>
        /// <returns></returns>
        public GridViewDatas HystereticData(string xDescp, string yDescp)
        {
            //初始化
            var dataList = new GridViewDatas("Hysteresis Loops");
            //获得勾选对象
            var elementList = this.ElementTagCheckListbox.GetObjects().ConvertAll(e => (ElementData)e);
            //遍历单元对象添加值
            elementList.ForEach(element =>
            {
                //获得列表
                var data = element.Data(xDescp, yDescp);
                //列表是否为空
                if(data.Count != 0)
                {
                    //创建序列
                    this.HysteresisChart.AddSeries(data.Name, SeriesChartType.Line, 2);
                    //添加绘图数据
                    this.HysteresisChart.Series[data.Name].Points.DataBindXY(
                        data[0].VALUES.ConvertAll(v => Convert.ToSingle(v)), 
                        data[1].VALUES.ConvertAll(v => Convert.ToSingle(v)));
                    //添加列表
                    dataList.AddRange(data);
                }
            });
            //返回结果
            return dataList;
        }

        #region CheckListbox

        /// <summary>
        /// 全选
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Hystersis_Select_All_Button_Click(object sender, EventArgs e)
        {
            this.ElementTagCheckListbox.CheckedAll();
        }

        /// <summary>
        /// 反选
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Hysteresis_Select_Inverse_Button_Click(object sender, EventArgs e)
        {
            this.ElementTagCheckListbox.InverseChecked();
        }

        /// <summary>
        /// 全选
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TimeHist_Select_All_Button_Click(object sender, EventArgs e)
        {
            this.TagChecklistbox.CheckedAll();
        }

        /// <summary>
        /// 反选
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TimeHist_Select_Inverse_Button_Click(object sender, EventArgs e)
        {
            this.TagChecklistbox.InverseChecked();
        }

        #endregion

        /// <summary>
        /// 绘制滞回曲线
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Hysteresis_Plot_Button_Click(object sender, EventArgs e)
        {
            //清空Chart
            this.HysteresisChart.Series.Clear();
            //获得滞回曲线数据
            var data = this.HystereticData(this.XAxisComboBox.Text, this.YAxisComboBox.Text);
            //设定坐标轴文字
            this.SetChartTitleText(new List<string> { "Hysteresis Loops",
                this.XAxisComboBox.Text, this.YAxisComboBox.Text});
            //DATAGIRDVIEW
            this.HysteresisDataGridView.AddDatas(data);
        }

        /// <summary>
        /// 绘制时程曲线
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TimeHist_Plot_Button_Click(object sender, EventArgs e)
        {
            //清空Chart
            this.HysteresisChart.Series.Clear();
            //获得数据
            var data = this.TimeHistData(this.ResponseComboBox.Text);
            //设定坐标轴文字
            this.SetChartTitleText(new List<string> { "Time History",
                this.TimeHistXML.isTimeEmpty? "": "Time",
                this.ResponseComboBox.Text });
            //DATAGIRDVIEW
            this.HysteresisDataGridView.AddDatas(data);
        }

        /// <summary>
        /// 帮助
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            HelpForm.Show(new List<string> { "OpenSEES XML Helper",
                "OpenSEES分析结果处理助手",
                "http://mp.weixin.qq.com/mp/homepage?__biz=MzU4NTQxMDc4Mg==&hid=4&sn=fbc49cc1dae11af1b42fc743f21b0b80&scene=18#wechat_redirect",
            "20191207"}, Properties.Resources.LOGO);
        }
    }
}
